SPB Git forge

spb/spb-cloud

Public
10commits 1branches 0releases
3.2 MBsize
maindefault branch
yesterdaylast push
JavaScript 56.7% TypeScript 42.6%
2.9 KB · 87 lines typescript
Raw Blame History
1import { NextRequest, NextResponse } from "next/server";2import { prisma } from "@/lib/prisma";3import { logActivity } from "@/lib/activity";4import { trashFiles } from "@/lib/trash";56export async function GET(7  request: NextRequest,8  { params }: { params: { id: string } }9) {10  const file = await prisma.file.findUnique({11    where: { id: params.id },12    include: { folder: true, sharedLinks: true, metadata: true, tags: { include: { tag: true } }, _count: { select: { versions: true } } },13  });1415  if (!file) {16    return NextResponse.json({ error: "File not found" }, { status: 404 });17  }1819  return NextResponse.json({ ...file, size: Number(file.size) });20}2122export async function PATCH(23  request: NextRequest,24  { params }: { params: { id: string } }25) {26  const body = await request.json().catch(() => ({}));27  const { name, folderId } = body as { name?: string; folderId?: string | null };2829  const file = await prisma.file.findUnique({ where: { id: params.id } });30  if (!file) {31    return NextResponse.json({ error: "File not found" }, { status: 404 });32  }3334  const updateData: Record<string, unknown> = {};3536  if (name !== undefined) {37    const trimmed = typeof name === "string" ? name.trim() : "";38    if (!trimmed) return NextResponse.json({ error: "Nom requis" }, { status: 400 });39    if (/[\\/]/.test(trimmed)) return NextResponse.json({ error: "Le nom ne peut pas contenir « / » ou « \\ »" }, { status: 400 });40    if (trimmed !== file.name) {41      updateData.name = trimmed;42      await logActivity("RENAME", params.id, `Renamed ${file.name} -> ${trimmed}`);43    }44  }4546  if (folderId !== undefined) {47    const target = folderId === "root" || folderId === null ? null : folderId;48    if (target) {49      const exists = await prisma.folder.findUnique({ where: { id: target }, select: { id: true } });50      if (!exists) return NextResponse.json({ error: "Dossier de destination introuvable" }, { status: 404 });51    }52    if (target !== file.folderId) {53      updateData.folderId = target;54      await logActivity("MOVE", params.id, `Moved ${file.name} to folder ${folderId}`);55    }56  }5758  if (Object.keys(updateData).length === 0) {59    return NextResponse.json({ ...file, size: Number(file.size) });60  }6162  const updated = await prisma.file.update({63    where: { id: params.id },64    data: updateData,65  });6667  return NextResponse.json({ ...updated, size: Number(updated.size) });68}6970/** Mise à la corbeille (restaurable 30 jours) — l'origine est mémorisée pour la restauration. */71export async function DELETE(72  request: NextRequest,73  { params }: { params: { id: string } }74) {75  const file = await prisma.file.findUnique({ where: { id: params.id }, select: { id: true, deletedAt: true } });76  if (!file) {77    return NextResponse.json({ error: "File not found" }, { status: 404 });78  }79  if (file.deletedAt) {80    return NextResponse.json({ success: true, alreadyTrashed: true });81  }8283  await trashFiles([file.id]);8485  return NextResponse.json({ success: true });86}87